package com.hu.example.proxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.sql.Connection;

import com.hu.core.context.AppContext;
import com.hu.core.util.DBUtil;

public class ConnectionDynamicProxy implements InvocationHandler{
    private Object target;

    public void setTarget(Object target) {
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Object result = null;
        ConnectionHolder connectionHolder = (ConnectionHolder)AppContext.getContext().getObject("APP_REQUEST_THREAD_CONNECTION");
        boolean needMyClose = false;
        boolean isCommitOrRollbackTran = false;

        if (connectionHolder == null) {
            Connection conn = DBUtil.getConnection();
            connectionHolder = new ConnectionHolder();
            connectionHolder.setConn(conn);
            if (method.getName().startsWith("save")) {
                DBUtil.setAutoCommit(conn, false);
                connectionHolder.setStartTran(true);
                isCommitOrRollbackTran = true;
            }

            AppContext.getContext().addObject("APP_REQUEST_THREAD_CONNECTION", connectionHolder);
            needMyClose = true;
        } else {
            if (method.getName().startsWith("save")) {
                if (!connectionHolder.isStartTran()) {
                    connectionHolder.setStartTran(true);
                    DBUtil.setAutoCommit(connectionHolder.getConn(), false);
                    isCommitOrRollbackTran = true;
                }
            }
        }

        try {
            result = method.invoke(target, args);
            if (method.getName().startsWith("save")) {
                if (isCommitOrRollbackTran) {
                    DBUtil.commit(connectionHolder.getConn());
                }
            }
        } catch (InvocationTargetException e) {
            System.out.println("here----------------------------");
            e.getCause();
            throw e.getTargetException();
        } catch (Throwable throwable) {
            throwable.getCause();
            if (method.getName().startsWith("save")) {
                if (isCommitOrRollbackTran) {
                    DBUtil.rollback(connectionHolder.getConn());
                }
            }

            throw throwable;
        }finally {
            if (needMyClose) {
                connectionHolder = (ConnectionHolder)AppContext.getContext().getObject("APP_REQUEST_THREAD_CONNECTION");
                DBUtil.close(connectionHolder.getConn(), null, null);
                AppContext.getContext().removeObject("APP_REQUEST_THREAD_CONNECTION");
                connectionHolder.setConn(null);
                connectionHolder = null;
            }
        }

        return result;
    }
}
